<?php
/**
 * @todo Remove unneccessary methods
 */
class PDOIterator implements Iterator {
    /**
     * @var PDOStatement
     */
    private $ps;
    
    /**
     * @var function
     */
    private $converter;
    
    /**
     * The current value
     * 
     * @var mixed
     */
    private $current;
    
    /**
     * @var array
     */
    private $next = null;
    
    /**
     * A little counter for rewind/key
     * @var int
     */
    private $i;
    
    /**
     *
     * @param PDOStatement $ps
     * @param callback $converter 
     */
    public function __construct(PDOStatement $ps, $converter) {
        $this->ps = $ps;
        $this->converter = $converter;
        $this->i = 0;
        
        $ps->setFetchMode(PDO::FETCH_ASSOC);
    }
    
    public function fetch() {
        if ($this->hasNext()) {
            $object = call_user_func($this->converter, $this->next);
            $this->next = null;
            ++$this->i;
            return $object;
        }
        else {
            throw new StopIterationException("No more data.");
        }
    }
    
    public function hasNext() {
        if ($this->next === null) {
            $this->next = $this->ps->fetch();
        }
        
        return $this->next !== false;
    }
    
    public function rewind() {
        if ($this->i !== 0) {
            throw new RuntimeException("You cannot rewind a PDOFetchable.");
        }
    }
    
    public function current() {
        if ($this->current === null) {
            $this->current = $this->fetch();
        }
        
        return $this->current;
    }
    
    public function key() {
        return key($this->ps);
    }
    
    public function next() {
        $this->current = null;
    }
    
    public function valid() {
        return $this->hasNext();
    }
}
